import string,math,spice_activeX,os.path,types



"""
The spiceload function described below is a general purpose routine for loading
a SPICE data file.

The general call to this method is the following:

x,y,e,labels=spiceload('HB1_exp0050_scan0002.dat',xvar='s1',yvar='s2',normcol='monitor',normconst=1)

Which will return numerical lists for x,y,e and a two-element list for labels where
labels[0] is the x-axis label and labels[1] is the y-axis label.

Other ways of calling the function:

x,y,e,labels=spiceload('HB1_exp0050_scan0002.dat')

This will load the default x and y values and will not do any normalization


x,y,e,labels=spiceload('HB1_exp0050_scan0002.dat',normcol='monitor',normconst=10000)

This will read in the default x and y and will normalize the data to monitor and multiply
by 10000.

NOTE: any combination of the arguments can be specified or not and defaults will be
substituted.

"""



def spiceload(filename,xvar=None,yvar=None,normcol=None,normconst=1):

    #Let's first check that the file exists
    file=open(filename,'r')
    text=file.readlines()
    headerlist=[]
    datalist=[]

    for lines in text:
        linetext=string.split(lines)
        if linetext[0]=='#':
            headerlist=headerlist+[lines]
            if linetext[1]=='def_x':
                defxval=linetext[3]
            elif linetext[1]=='def_y':
                defyval=linetext[3]
                
        else:
            datalist=datalist+[lines]

    linecount=0
    columns=""

    for header in headerlist:
        headertxt=string.split(header)
        if headertxt[1] == 'col_headers':
            columns=string.split(headerlist[linecount+1])
            columnlist=columns[1:]
        linecount+=1



# Now look to see if xvar and yvar have been specified
# An error will occur if they've been specified but don't exist


    #xheader=""
    #yheader=""

     if xvar:
        xvarvalid=xvar in columnlist
        if xvarvalid == 1:
            xcolindex=columnlist.index(xvar)
            xheader=columnlist[xcolindex]
        else:
            raise Exception, "The x-column name " + xvar + " is not valid"

    else:
        xcolindex=columnlist.index(defxval)
        xheader=columnlist[xcolindex]

    if yvar:
        yvarvalid=yvar in columnlist
        if yvarvalid == 1:
            ycolindex=columnlist.index(yvar)
            yheader=columnlist[ycolindex]
        else:
            raise Exception, "The y-column name " + yvar + " is not valid"

    else:
        ycolindex=columnlist.index(defyval)
        yheader=columnlist[ycolindex]

    # Now check to see if monitor is specified:

    if normcol:
        normvalid=normcol in columnlist
        if normvalid == 1:
            normcolindex=columnlist.index(normcol)
            normheader=columnlist[normcolindex]
        else:
            raise Exception, "The normalization column name " + str(normcol) + " is not valid"
    else:
        normcolindex=-1
        normheader=""

    errtmp=[]
    xvalue=[]
    ytmp=[]

    # Pull off x and y values, calculate error and normalize y and error to normconst

    for data in datalist:
        dataline=string.split(data)
        thisx=string.atof(dataline[xcolindex])
        xvalue.append(thisx)
        thisy=string.atof(dataline[ycolindex])
        ytmp.append(thisy*normconst)
        errtmp.append(math.sqrt(thisy)*normconst)
                

    errval=[]
    yvalue=[]



    # This will divide by the normalization column if specified
    
    if normcolindex == -1:
        yvalue=ytmp
        errval=errtmp
    else:
        counter=0
        yheader=yheader + " / " + normheader
        for data in datalist:
            dataline=string.split(data)
            normval=string.atof(dataline[normcolindex])
            yvalue.append(ytmp[counter]/normval)
            errval.append(errtmp[counter]/normval)
            counter+=1

    if normconst == 1:
        yheader = yheader
    else:
        yheader = yheader + " * " + str(normconst)

    labels=[xheader,yheader]

    return xvalue, yvalue, errval, labels

"""
This function will load the last spice data file by pulling the relevant information
from SPICE via an activeX call.

This assumes that the spicemodule has already been loaded.
"""

def loadlast(xvar=None,yvar=None,normcol=None,normconst=1):
    spicesession=spice_activeX.Application()
    bufferglobals=spicesession.GetVIReference('buffer_global.vi')
    exptglobals=spicesession.GetVIReference('experiment_globals.vi')
    datafiledir=bufferglobals.GetControlValue('Datafile Dir')
    instname=exptglobals.GetControlValue('Instrument')
    exptnumber=exptglobals.GetControlValue('Current Experiment')
    nextscan=exptglobals.GetControlValue('Next Scan Number')
    lastscan=nextscan-1
    scanname="%s_exp%04d_scan%04d.dat" % (instname,exptnumber,lastscan)
    fullpath=os.path.join(datafiledir,scanname)
    xloc,yloc,errloc,labelsloc=spiceload(fullpath,xvar,yvar,normcol,normconst)
    return xloc,yloc,errloc,labelsloc


def loadscan(ScanNo,xvar=None,yvar=None,normcol=None,normconst=1):
    spicesession=spice_activeX.Application()
    bufferglobals=spicesession.GetVIReference('buffer_global.vi')
    exptglobals=spicesession.GetVIReference('experiment_globals.vi')
    datafiledir=bufferglobals.GetControlValue('Datafile Dir')
    instname=exptglobals.GetControlValue('Instrument')
    exptnumber=exptglobals.GetControlValue('Current Experiment')
    nextscan=exptglobals.GetControlValue('Next Scan Number')
    lastscan=nextscan-1

    if type(ScanNo) == types.FloatType:
        ScanNo=int(round(ScanNo))
    elif type(ScanNo) == types.StringType:
        ScanNo=int(round(string.atof(ScanNo)))

    if ScanNo > lastscan:
       errortext="The scan number " + str(ScanNo) + " exceeds the last scan in the experiment"
       raise errortext
    else:
       scanname="%s_exp%04d_scan%04d.dat" % (instname,exptnumber,ScanNo)
       fullpath=os.path.join(datafiledir,scanname)
       x,y,err,labels=spiceload(fullpath,xvar,yvar,normcol,normconst)
        






    return x,y,err,labels

